import 'dart:async';
import 'dart:io';

import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

enum WebViewLoadStatus { loading, staring, finished, error, noNetwork }

///进度条的回调，返回控制代理
typedef void ProgressCreateCallBack(ProgressController progressController);

const String androidUserAgent =
    "Mozilla/5.0 (Linux; Android 7.0.0; U; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1/jincheng";

const String iosUserAgent =
    "Mozilla/5.0 (iPhone; U; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5/jincheng";

//webview创建回调
typedef WebViewCreatedCallback = void Function(WebViewController controller);

//request 拦截回调
typedef NavigationRequestDelegate = FutureOr<NavigationDecision> Function(
    NavigationRequest navigation);

/// Signature for when a [WebView] has started loading a page.
typedef PageStartedCallback = void Function(String url);

/// Signature for when a [WebView] is loading a page.
typedef PageLoadingCallback = void Function(int progress);

/// Signature for when a [WebView] has finished loading a page.
typedef PageFinishedCallback = void Function(String url);

/// Signature for when a [WebView] has failed to load a resource.
typedef WebResourceErrorCallback = void Function(WebResourceError error);

typedef UrlChangeCallback = void Function(UrlChange change);

///带加载进度条的webView
class ProgressWebView extends StatefulWidget {
  final String initialUrl; //要显示的url
  final bool encodeFull; //是否编译
  final String? userAgent;
  final Map<String, Function(JavaScriptMessage)>?
      javascriptChannels; // JS可以调用Flutter

  final bool showPlaceholder; //是否显示占位
  final bool checkNoNetwork; //是否检查无网络
  final Duration? delayedDuration; //完成 延时时间
  final ProgressCreateCallBack? onProgressCreated;
  final WebViewCreatedCallback? onWebViewCreated; //创建完成调用
  final NavigationRequestDelegate? navigationDelegate; //拦截请求
  final PageStartedCallback? onPageStarted; //页面开始加载时调用
  final PageLoadingCallback? onPageLoading; //页面加载中调用
  final PageFinishedCallback? onPageFinished; //页面加载完成时调用
  final UrlChangeCallback? onUrlChange; //url改变

  final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers; //手势
  final bool gestureNavigationEnabled;

  final bool injectFontFamily; //是否整个页面注入字体
  final bool injectTitleFontFamily; //是否标题（订阅号名称）注入字体

  const ProgressWebView({
    Key? key,
    required this.initialUrl,
    this.encodeFull = true,
    this.userAgent,
    this.javascriptChannels,
    this.onProgressCreated,
    this.onWebViewCreated,
    this.navigationDelegate,
    this.onPageStarted,
    this.onPageLoading,
    this.onPageFinished,
    this.onUrlChange,
    this.injectFontFamily = true,
    this.injectTitleFontFamily = true,
    this.gestureNavigationEnabled = true,
    this.gestureRecognizers,
    this.delayedDuration,
    this.showPlaceholder = true,
    this.checkNoNetwork = true,
  }) : super(key: key);

  @override
  _ProgressWebViewState createState() => _ProgressWebViewState();
}

class _ProgressWebViewState extends State<ProgressWebView> {
  late String _url;
  late WebViewController _controller;
  late ProgressController _progressController;
  late WebViewLoadStatus _loadStatus;

  late DateTime initDate; //initState() 进入时间
  late DateTime startedDate; //onPageStarted()  回调时间
  late DateTime finishedDate; //onPageFinished() 回调时间

  @override
  void initState() {
    super.initState();
    _url = widget.initialUrl;
    _progressController = ProgressController._(this);

    _loadStatus = WebViewLoadStatus.loading;
    if (null != widget.onProgressCreated) {
      widget.onProgressCreated?.call(_progressController);
    }

    initWebViewController();

    print('进入网页时间:${initDate = DateTime.now()}');
    startedDate = DateTime.now();
    finishedDate = DateTime.now();
  }

  void initWebViewController() {
    String url = _url;
    if (Platform.isIOS && widget.encodeFull) {
      url = Uri.encodeFull(_url);
    }

    // #docregion platform_features
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        // mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
        WebViewController.fromPlatformCreationParams(params);

    //安卓平台设置
    if (controller.platform is AndroidWebViewController) {
      final AndroidWebViewController androidController =
          controller.platform as AndroidWebViewController;

      AndroidWebViewController.enableDebugging(true);
      androidController.setMediaPlaybackRequiresUserGesture(false);

      //处理文件选择，只有 AndroidWebViewController 才暴露出 setOnShowFileSelector 方法，这里才能监听文件选择
      androidController.setOnShowFileSelector((params) async {
        if (params.acceptTypes.any((type) => type == 'image/*')) {
          String? path = await clickImage();
          if (path != null && path.isNotEmpty) {
            return [path];
          }
        }
        return [];
      });
    }

    try {
      String userAgent = widget.userAgent ??
          (Platform.isIOS ? iosUserAgent : androidUserAgent);
      controller.setUserAgent(userAgent);
      controller.setJavaScriptMode(JavaScriptMode.unrestricted);

      if (widget.javascriptChannels?.isNotEmpty ?? false) {
        widget.javascriptChannels?.forEach((key, value) {
          controller.addJavaScriptChannel(key, onMessageReceived: value);
        });
      }

      NavigationDelegate delegate = NavigationDelegate(
          onNavigationRequest: (NavigationRequest navigation) {
        print(
            'NavigationRequest ===>  url:${navigation.url}  isForMainFrame:${navigation.isMainFrame}');
        if (navigation.url.isEmpty || navigation.url == "about:blank") {
          return NavigationDecision.prevent;
        }
        return widget.navigationDelegate?.call(navigation) ??
            NavigationDecision.navigate;
      }, onPageStarted: (url) {
        print('onPageStarted时间:${startedDate = DateTime.now()}');
        if (null != widget.onPageStarted) {
          widget.onPageStarted?.call(url);
        }
      }, onProgress: (progress) {
        // print('onProgress加载进度:$progress');
        // if (null != widget.onPageLoading) {
        //   widget.onPageLoading?.call(progress);
        // }
      }, onPageFinished: (url) {
        print('onPageFinished时间:${finishedDate = DateTime.now()}');
        print('dom渲染耗费时间 ${finishedDate.difference(initDate)}');
        _handleOnPageFinished(url);
        if (widget.onPageFinished != null) {
          widget.onPageFinished?.call(url);
        }
      }, onWebResourceError: (error) {
        print(
            '网页加载出错了 code: ${error.errorCode} description: ${error.description}  errorType: ${error.errorType}  isForMainFrame: ${error.isForMainFrame}');
        // 注释原因: WebView部分报错会导致页面不能查看
        // if (mounted) {
        //   setState(() => _loadStatus = WebViewLoadStatus.error);
        // }
      }, onUrlChange: (change) {
        print('onUrlChange:${change.url}');
        widget.onUrlChange?.call(change);
      });
      controller
        ..setNavigationDelegate(delegate)
        ..loadRequest(Uri.parse(url));
    } catch (e) {
      print('initWebViewController() $e');
      if (mounted) {
        setState(() => _loadStatus = WebViewLoadStatus.error);
      }
    }
    _controller = controller;
    if (widget.onWebViewCreated != null) {
      widget.onWebViewCreated?.call(_controller);
    }
  }

  Future _handleOnPageFinished(String url) async {
    /// 设置了进度的代理，自己处理进度条的消失（详情页、非外联、非跳转）
    if (null == widget.onProgressCreated) {
      if (widget.delayedDuration != null) {
        await Future.delayed(widget.delayedDuration!);
      }
      if (mounted) {
        setState(() {
          DateTime _finishedDate;
          print('网页显示出来时间:${_finishedDate = DateTime.now()}');
          print('加载数据耗费时间 ${_finishedDate.difference(finishedDate)}');
          print('总消耗时间 ${_finishedDate.difference(initDate)}');

          _loadStatus = WebViewLoadStatus.finished;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    Widget placeholder = SizedBox();

    WebViewWidget webView = WebViewWidget(
      controller: _controller,
      gestureRecognizers: widget.gestureRecognizers ??
          (Platform.isAndroid
              ? (Set()
                ..add(Factory<EagerGestureRecognizer>(
                    () => EagerGestureRecognizer())))
              : Set()
            ..add(Factory<PanGestureRecognizer>(() => PanGestureRecognizer()))),
    );

    return webView;
  }

  ///隐藏进度条
  _changeLoadStatus(WebViewLoadStatus loadStatus) {
    if (loadStatus == WebViewLoadStatus.finished) {
      DateTime _finishedDate;
      print('网页loading结束时间:${_finishedDate = DateTime.now()}');
      print('加载数据耗费时间 ${_finishedDate.difference(finishedDate)}');
      print('总消耗时间 ${_finishedDate.difference(initDate)}');
    }
    if (_loadStatus != loadStatus && mounted)
      setState(() => _loadStatus = loadStatus);
  }

  Future<String?> clickImage() async {
    final PermissionState permissionState =
        await PhotoManager.requestPermissionExtend();
    if (!permissionState.isAuth) {
      return null;
    }

    AssetPickerConfig pickerConfig = AssetPickerConfig(
      maxAssets: 1,
      pageSize: 320,
      pathThumbnailSize: ThumbnailSize(200, 200),
      requestType: RequestType.image,
      gridCount: 4,
      pickerTheme: AssetPicker.themeData(Color(0xff00bc56)),
      specialItemPosition: SpecialItemPosition.prepend,
      specialItemBuilder:
          (BuildContext context, AssetPathEntity? path, int length) {
        return GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: () async {
            final AssetEntity? result = await CameraPicker.pickFromCamera(
              context,
              // isAllowRecording: true,
            );
            if (result != null) {
              Navigator.of(context).pop(<AssetEntity>[result]);
            }
          },
          child: const Center(
            child: Icon(Icons.camera_enhance, size: 42.0),
          ),
        );
      },
    );

    List<AssetEntity>? assets =
        await AssetPicker.pickAssets(context, pickerConfig: pickerConfig);

    if (assets != null && assets.length > 0) {
      AssetEntity entity = assets.first;
      File? file = await entity.file;

      return file?.uri.toString() ?? '';
    }

    return null;
  }
}

///进度的控制器
class ProgressController {
  _ProgressWebViewState _progressWebView;

  ProgressController._(this._progressWebView);

  setLoadStatus(WebViewLoadStatus loadStatus) {
    _progressWebView._changeLoadStatus(loadStatus);
  }

  WebViewLoadStatus getLoadStatus() {
    return _progressWebView._loadStatus;
  }
}
